import pygame
import random
import math
import time
import sys

from pygame.constants import KEYDOWN, K_ESCAPE, K_SPACE, K_UP  # 引入数学模块

while True:  # 建立大循环，使游戏可以反复重启
    # 1. 初始化界面
    clock = pygame.time.Clock()

    pygame.init()
    screen = pygame.display.set_mode((800, 600))
    pygame.display.set_caption('星际大战')
    icon = pygame.image.load('images\\ufo.png')
    pygame.display.set_icon(icon)
    bgImg = pygame.image.load('images\\space.png')

    # 添加背景音效
    pygame.mixer.music.load('sounds\\bg.wav')
    pygame.mixer.music.play(-1)  # 单曲循环
    # 创建射中音效
    bao_sound = pygame.mixer.Sound('sounds\\exp.wav')

    # 5.飞机
    playerImg = pygame.image.load('images\\4.png')
    playerX = 350  # 玩家的X坐标
    playerY = 500  # 玩家的Y坐标
    playerStepX = 0  # 玩家移动的速度
    playerStepY = 0

    # 分数
    score = 0
    font = pygame.font.SysFont('arial', 32)


    # 显示分数
    def show_score():
        text = f"Score: {score}"
        score_render = font.render(text, True, (255, 255, 255))
        screen.blit(score_render, (10, 10))


    # 显示难度等级，即速度因子
    def show_level():
        text = f"level: {speed_factor}"
        level_render = font.render(text, True, (255, 255, 255))
        screen.blit(level_render, (650, 10))


    # 游戏结束
    is_over = False

    over_font = pygame.font.Font('freesansbold.ttf', 64)

    # 游戏开始
    play_active = False
    restart = False
    on_font = pygame.font.SysFont('candara', 32)


    def check_is_on():
        if play_active == False and is_over == False:
            text = "Press Backspace To Start"
            render = on_font.render(text, True, (255, 215, 0))
            screen.blit(render, (230, 350))


    def check_is_over():
        if is_over:
            text1 = "Game Over"
            render = over_font.render(text1, True, (255, 0, 0))
            screen.blit(render, (200, 250))
            text2 = "Press Delete To Restart"
            render = on_font.render(text2, True, (255, 215, 0))
            screen.blit(render, (225, 400))


    # 9. 添加敌人
    number_of_enemies = 4  # 敌人的数量

    # 敌人类
    speed_factor = 1


    class Enemy():
        def __init__(self):
            self.img = pygame.image.load('images\\UFO.png')
            self.x = random.randint(200, 600)
            self.y = random.randint(50, 250)
            self.step = random.randint(1, 3)  # 敌人移动的速度

        # 当被射中时，恢复位置
        def reset(self):
            self.x = random.randint(200, 600)
            self.y = random.randint(50, 200)


    enemies = []  # 保存所有的敌人
    for i in range(number_of_enemies):
        enemies.append(Enemy())


    # 两个点之间的距离
    def distance(bx, by, ex, ey):
        a = bx - ex
        b = by - ey
        return math.sqrt(a * a + b * b)  # 开根号


    # 子弹类
    class Bullet():
        def __init__(self):
            self.img = pygame.image.load('images\\new_bullet.png')
            self.x = playerX + 20
            self.y = playerY - 80
            self.step = 6  # 子弹移动的速度

        # 击中
        def hit(self):
            global score
            global speed_factor
            global bullets_number
            for e in enemies:
                if distance(self.x, self.y, e.x, e.y) < 50:
                    # 射中啦
                    bao_sound.play()
                    try:
                        bullets.remove(self)
                        bullets_number -= 1
                    except ValueError:
                        print('忽略了一个错误')
                    e.reset()
                    score += 1
                    speed_factor = score // 20 + 1  # 分数每上升20分，速度因子就增加一级
                    # print(score)


    bullets = []  # 保存现有的子弹

    bullets_number = 0  # 屏幕上存在的子弹


    # 显示并移动子弹
    def show_bullets():
        global bullets_number
        for b in bullets:
            screen.blit(b.img, (b.x, b.y))
            b.hit()  # 看看是否击中了敌人
            b.y -= b.step  # 移动子弹
            # 判断子弹是否出了界面，如果出了就移除掉
            if b.y < 0:
                bullets.remove(b)
                bullets_number -= 1


    # 显示敌人，并且实现敌人的移动和下沉
    def show_enemy():
        global is_over
        global play_active
        global restart
        for e in enemies:
            screen.blit(e.img, (e.x, e.y))
            e.x += e.step * (1 + 0.15 * speed_factor)  # 根据速度因子增加敌人水平移动的速度
            if e.x > 736 or e.x < 0:
                e.step *= -1
                e.y += 65 * (1 + 0.1 * speed_factor)  # 根据速度因子增加敌人下沉的速度
                if e.y > 450:
                    is_over = True
                    play_active = False
                    restart = True
                    # print("游戏结束啦")
                    enemies.clear()


    def move_player():
        global playerX
        playerX += playerStepX
        # 防止飞机出界
        if playerX > 736:
            playerX = 736
        if playerX < 0:
            playerX = 0


    # 2. 游戏主循环

    running = True
    while running:
        screen.blit(bgImg, (0, 0))
        clock.tick(120)  # Now your game will be capped at 120 fps，控制运行速度
        show_score()  # 显示分数
        show_level()  # 显示难度等级
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

            if event.type == pygame.KEYDOWN:  # 按下就移动
                if event.key == pygame.K_ESCAPE:
                    # 按Esc退出游戏
                    running = False
                if event.key == pygame.K_BACKSPACE:
                    # 按Backspace开始游戏
                    play_active = True
                    # restart = False
                if play_active == True:
                    # 通过键盘事件控制飞机的移动

                    if event.key == pygame.K_RIGHT:
                        playerStepX = 8
                    elif event.key == pygame.K_LEFT:
                        playerStepX = -8
                    elif event.key == pygame.K_SPACE and bullets_number < 2:  # 只有当屏幕上子弹不多于两枚时，才能射击
                        # print('发射子弹....')
                        # 创建一颗子弹
                        bullets.append(Bullet())
                        bullets_number += 1
                if restart == True:
                    if event.key == pygame.K_DELETE:
                        # 按delete键，进入下一个大循环，游戏重新开始
                        running = False


            if event.type == pygame.KEYUP:  # 抬起来就不动
                playerStepX = 0

        screen.blit(playerImg, (playerX, playerY))
        move_player()  # 移动玩家
        if play_active == True:
            show_enemy()  # 显示敌人
        show_bullets()  # 显示子弹
        check_is_on()  # 游戏开始
        check_is_over()  # 显示游戏结束字段
        pygame.display.update()
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_ESCAPE:
            # 退出大循环
            break
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_DELETE:
            # 重启游戏
            play_active = True
            running = True
            restart = False
